const path = require('path')
const favicon = require('serve-favicon')
const compress = require('compression')
const cors = require('cors')
const helmet = require('helmet')
const express = require('express')
const bugsnag = require('bugsnag')
const ResponseError = require('./helper/ResponseError')
const createModel = require('./model')
const logRequest = require('./middleware/logRequest')
const authoriseUser = require('./middleware/authoriseUser')
const addResponseError = require('./middleware/addResponseError')
const addRequestContext = require('./middleware/addRequestContext')
const adminService = require('./service/admin')
const errorHandler = require('./helper/errorHandler')
const { APP_LAUNCH_HOST } = require('./config')

const app = express()

// add res.error to handle ResponseError object
app.use(addResponseError)

// cors: providing a Connect/Express middleware that can be used to enable CORS.
app.use(cors())

// helmet: secure Express apps by setting various HTTP headers
app.use(helmet())

// compress: support compression codings of gzip and deflate
app.use(compress())

// parses incoming requests with JSON payloads and is based on body-parser.
app.use(express.json())

// parses incoming requests with urlencoded payloads and is based on body-parser.
app.use(express.urlencoded({ extended: true }))

// serve-favicon: middleware for serving a favicon
app.use(favicon(path.join('public', 'favicon.ico')))

// print request method and path
process.env.NODE_ENV === 'development' && app.use(logRequest)

// add req context empty object
app.use(addRequestContext)

// parse and check access token
app.use(authoriseUser)

// Host the public folder
// app.use('/', express.static('public'));

// Create models
createModel()

// Redirect / to main website
app.get('/', (req, res) => {
  res.redirect(APP_LAUNCH_HOST)
})


app.get('/ping', (req, res) => {
  res.status(200)
  res.json({ ping: 'ok' })
})

// set serviecs
// adminServices handles all apis for admin panel
app.use('/admin', adminService)

// Configure a middleware for 404s
app.use((req, res) => {
  res.error(new ResponseError.NotFound())
})

// Configure a middleware for the error handler
// Handle all non-500 errors
app.use((err, req, res, next) => { // eslint-disable-line
  const errors = [].concat(err)
  const handledErrors = errors.map(errorHandler)
  if (handledErrors[0].code !== 500) {
    res.error(handledErrors)
  } else {
    next(err)
  }
})
// only add bugsnag error handler for 500
app.use(bugsnag.errorHandler)
// handle all 500 errors
app.use((err, req, res, next) => { // eslint-disable-line
  const errors = [].concat(err)
  const handledErrors = errors.map(errorHandler)
  res.error(handledErrors)
})

module.exports = app
